using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using NPOI.XSSF.UserModel;
using NPOI.SS.UserModel;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Linq;
using System;
using NPOI.SS.Util;
using System.Text.Json.Serialization;
using B.S.Medical.ErrorCode;
using B.S.Medical.Domain.Doctor;
using B.S.Medical.Domain.Department;
using B.S.Medical.Infrastructure.Interface;

namespace B.S.Medical.Api.Write.Controllers.Doc
{
    /// <summary>
    /// 医生导入导出
    /// </summary>
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class DoctorImportController : ControllerBase
    {
        /// <summary>
        /// 下载医生导入Excel模板
        /// </summary>
        [HttpGet]
        public IActionResult DownloadTemplate()
        {
            var workbook = new XSSFWorkbook();
            var sheet = workbook.CreateSheet("医生导入模板");
            var header = sheet.CreateRow(0);
            header.CreateCell(0).SetCellValue("医生姓名");
            header.CreateCell(1).SetCellValue("照片");
            header.CreateCell(2).SetCellValue("院区");
            header.CreateCell(3).SetCellValue("科室");
            header.CreateCell(4).SetCellValue("医生职称");
            header.CreateCell(5).SetCellValue("挂号费");
            header.CreateCell(6).SetCellValue("诊查费");
            header.CreateCell(7).SetCellValue("医生简介");
            header.CreateCell(8).SetCellValue("标签");
            header.CreateCell(9).SetCellValue("医生状态");

            var stream = new MemoryStream();
            workbook.Write(stream, true);
            stream.Position = 0;
            return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "医生导入模板.xlsx");
        }

        /// <summary>
        /// 导入医生信息（Excel上传）
        /// </summary>
        /// <param name="file">上传的Excel文件（模板格式）</param>
        /// <returns>导入结果</returns>
        /// <remarks>
        /// 1. 请先下载模板，按模板填写数据后上传。
        /// 2. 支持xlsx格式，表头需与模板一致。
        /// 3. 系统会逐行读取数据并保存到数据库。
        /// 4. 标签等多值字段请用英文逗号分隔。
        /// 5. 导入前请确保院区、科室、职称、标签等基础数据已存在。
        /// </remarks>
        [HttpPost]
        public async Task<IActionResult> Import(
            IFormFile file,
            [FromServices] IBaseRepository<DoctorModel> doctorRepo,
            [FromServices] IBaseRepository<ManageModel> departmentRepo,
            [FromServices] IBaseRepository<CampusModel> campusRepo,
            [FromServices] IBaseRepository<JobTitleModel> jobTitleRepo,
            [FromServices] IBaseRepository<LabelModel> labelRepo,
            [FromServices] IBaseRepository<DoctorLabelModel> doctorLabelRepo)
        {
            if (file == null || file.Length == 0)
                return BadRequest("请上传Excel文件");

            try
            {
                // 创建结果信息
                var importResult = new ImportResultDto
                {
                    TotalRows = 0,
                    SuccessCount = 0,
                    FailedCount = 0,
                    ErrorMessages = new List<string>()
                };

                // 读取Excel文件
                using (var stream = new MemoryStream())
                {
                    await file.CopyToAsync(stream);
                    stream.Position = 0;
                    var workbook = new XSSFWorkbook(stream);
                    var sheet = workbook.GetSheetAt(0);
                    
                    // 如果没有数据行，直接返回
                    if (sheet.LastRowNum < 1)
                    {
                        return Ok(new { Message = "导入文件中没有数据", Result = importResult });
                    }
                    
                    importResult.TotalRows = sheet.LastRowNum;

                    // 0. 打印Excel表头和几行数据，帮助调试
                    var headerRow = sheet.GetRow(0);
                    var headers = new List<string>();
                    for (int i = 0; i < headerRow.LastCellNum; i++)
                    {
                        headers.Add(headerRow.GetCell(i)?.ToString());
                    }
                    Console.WriteLine($"Excel表头: {string.Join(", ", headers)}");
                    
                    // 打印前3行数据
                    for (int row = 1; row <= Math.Min(3, sheet.LastRowNum); row++)
                    {
                        var dataRow = sheet.GetRow(row);
                        if (dataRow == null) continue;
                        
                        var rowData = new List<string>();
                        for (int i = 0; i < dataRow.LastCellNum; i++)
                        {
                            rowData.Add(dataRow.GetCell(i)?.ToString() ?? "空");
                        }
                        Console.WriteLine($"第{row}行数据: {string.Join(", ", rowData)}");
                    }
                
                    // 1. 提取所有需要查找的名称
                    var allCampusNames = new HashSet<string>();
                    var allDepartmentNames = new HashSet<string>();
                    var allJobTitleNames = new HashSet<string>();
                    var allLabelNames = new HashSet<string>();
                    
                    for (int row = 1; row <= sheet.LastRowNum; row++)
                    {
                        var dataRow = sheet.GetRow(row);
                        if (dataRow == null) continue;
                        
                        // 提取院区名称
                        var campusName = dataRow.GetCell(2)?.ToString();
                        if (!string.IsNullOrWhiteSpace(campusName))
                        {
                            allCampusNames.Add(campusName.Trim());
                        }
                        
                        // 提取科室名称
                        var departmentName = dataRow.GetCell(3)?.ToString();
                        if (!string.IsNullOrWhiteSpace(departmentName))
                        {
                            allDepartmentNames.Add(departmentName.Trim());
                        }
                        
                        // 提取职称名称
                        var jobTitleName = dataRow.GetCell(4)?.ToString();
                        if (!string.IsNullOrWhiteSpace(jobTitleName))
                        {
                            allJobTitleNames.Add(jobTitleName.Trim());
                        }
                        
                        // 提取标签名称
                        var labelsStr = dataRow.GetCell(8)?.ToString();
                        if (!string.IsNullOrWhiteSpace(labelsStr))
                        {
                            var labelsList = labelsStr.Split(',', StringSplitOptions.RemoveEmptyEntries);
                            foreach (var label in labelsList)
                            {
                                allLabelNames.Add(label.Trim());
                            }
                        }
                    }
                    
                    Console.WriteLine($"提取到的院区名称: {string.Join(", ", allCampusNames)}");
                    Console.WriteLine($"提取到的科室名称: {string.Join(", ", allDepartmentNames)}");
                    Console.WriteLine($"提取到的职称名称: {string.Join(", ", allJobTitleNames)}");
                    Console.WriteLine($"提取到的标签名称: {string.Join(", ", allLabelNames)}");
                    
                    
                    // 2. 批量查询各实体名称到ID的映射
                    // 院区映射
                    var campusMap = campusRepo.GetAll()
                        .Where(c => allCampusNames.Contains(c.CampusName) && !c.IsDeleted)
                        .ToDictionary(c => c.CampusName, c => c.Id);
                    
                    // 科室映射
                    var departmentMap = departmentRepo.GetAll()
                        .Where(d => allDepartmentNames.Contains(d.DepartmentName) && !d.IsDeleted)
                        .ToDictionary(d => d.DepartmentName, d => d.Id);
                    
                    // 职称映射
                    var jobTitleMap = jobTitleRepo.GetAll()
                        .Where(j => allJobTitleNames.Contains(j.JobTitle) && !j.IsDeleted)
                        .ToDictionary(j => j.JobTitle, j => j.Id);
                    
                    // 标签映射
                    var labelMap = labelRepo.GetAll()
                        .Where(l => allLabelNames.Contains(l.Label) && !l.IsDeleted)
                        .ToDictionary(l => l.Label, l => l.Id);
                    
                    // 记录未找到的名称
                    var notFoundCampuses = allCampusNames.Where(name => !campusMap.ContainsKey(name)).ToList();
                    var notFoundDepartments = allDepartmentNames.Where(name => !departmentMap.ContainsKey(name)).ToList();
                    var notFoundJobTitles = allJobTitleNames.Where(name => !jobTitleMap.ContainsKey(name)).ToList();
                    var notFoundLabels = allLabelNames.Where(name => !labelMap.ContainsKey(name)).ToList();
                    
                    // 如果有未找到的名称，记录错误信息
                    if (notFoundCampuses.Any())
                        importResult.ErrorMessages.Add($"找不到以下院区: {string.Join(", ", notFoundCampuses)}");
                    if (notFoundDepartments.Any())
                        importResult.ErrorMessages.Add($"找不到以下科室: {string.Join(", ", notFoundDepartments)}");
                    if (notFoundJobTitles.Any())
                        importResult.ErrorMessages.Add($"找不到以下职称: {string.Join(", ", notFoundJobTitles)}");
                    if (notFoundLabels.Any())
                        importResult.ErrorMessages.Add($"找不到以下标签: {string.Join(", ", notFoundLabels)}");
                    
                    // 打印找到的映射信息
                    Console.WriteLine("找到的映射关系：");
                    Console.WriteLine("院区映射:");
                    foreach (var item in campusMap)
                    {
                        Console.WriteLine($"  院区名称: {item.Key}, ID: {item.Value}");
                    }
                    
                    Console.WriteLine("科室映射:");
                    foreach (var item in departmentMap)
                    {
                        Console.WriteLine($"  科室名称: {item.Key}, ID: {item.Value}");
                    }
                    
                    Console.WriteLine("职称映射:");
                    foreach (var item in jobTitleMap)
                    {
                        Console.WriteLine($"  职称名称: {item.Key}, ID: {item.Value}");
                    }
                    
                    // 3. 逐行处理数据
                    for (int row = 1; row <= sheet.LastRowNum; row++)
                    {
                        try
                        {
                            var dataRow = sheet.GetRow(row);
                            if (dataRow == null) continue;
                            
                            // 读取每一列数据
                            var doctorName = dataRow.GetCell(0)?.ToString()?.Trim();
                            var photo = dataRow.GetCell(1)?.ToString()?.Trim();
                            var campusName = dataRow.GetCell(2)?.ToString()?.Trim();
                            var departmentName = dataRow.GetCell(3)?.ToString()?.Trim();
                            var jobTitleName = dataRow.GetCell(4)?.ToString()?.Trim();
                            
                            var copayfeeStr = dataRow.GetCell(5)?.ToString()?.Trim();
                            var consultationfeeStr = dataRow.GetCell(6)?.ToString()?.Trim();
                            var briefly = dataRow.GetCell(7)?.ToString()?.Trim();
                            var labelsStr = dataRow.GetCell(8)?.ToString()?.Trim();
                            var statusStr = dataRow.GetCell(9)?.ToString()?.Trim();
                            
                            // 数据有效性检查
                            if (string.IsNullOrEmpty(doctorName))
                            {
                                importResult.ErrorMessages.Add($"第{row}行: 医生姓名不能为空");
                                importResult.FailedCount++;
                                continue;
                            }
                            
                            // 将名称转换为ID
                            if (!campusMap.TryGetValue(campusName, out int campusId) ||
                                !departmentMap.TryGetValue(departmentName, out int departmentId) ||
                                !jobTitleMap.TryGetValue(jobTitleName, out int jobTitleId))
                            {
                                importResult.ErrorMessages.Add($"第{row}行: {doctorName} - 院区、科室或职称数据无效");
                                importResult.FailedCount++;
                                continue;
                            }
                            
                            // 解析挂号费和诊查费
                            decimal copayfee = 0;
                            if (!string.IsNullOrEmpty(copayfeeStr) && !decimal.TryParse(copayfeeStr, out copayfee))
                            {
                                importResult.ErrorMessages.Add($"第{row}行: {doctorName} - 挂号费格式不正确");
                                importResult.FailedCount++;
                                continue;
                            }
                            
                            decimal consultationfee = 0;
                            if (!string.IsNullOrEmpty(consultationfeeStr) && !decimal.TryParse(consultationfeeStr, out consultationfee))
                            {
                                importResult.ErrorMessages.Add($"第{row}行: {doctorName} - 诊查费格式不正确");
                                importResult.FailedCount++;
                                continue;
                            }
                            
                            // 解析状态
                            bool status = statusStr == "启用";
                            
                            // 创建医生对象
                            var doctor = new DoctorModel
                            {
                                DoctorName = doctorName,
                                Photo = photo,
                                CampusId = campusId,
                                DepartmentId = departmentId,
                                JobTitleId = jobTitleId,
                                Copayfee = copayfee,
                                Consultationfee = consultationfee,
                                Briefly = briefly,
                                Status = status,
                                IsDeleted = false
                            };
                            
                            // 保存医生信息
                            Console.WriteLine($"正在保存医生: {doctor.DoctorName}, 科室ID: {doctor.DepartmentId}, 院区ID: {doctor.CampusId}, 职称ID: {doctor.JobTitleId}");
                            int result = await doctorRepo.CreateAsync(doctor);
                            int doctorId = doctor.Id; // 获取保存后的ID
                            Console.WriteLine($"医生保存结果: 影响行数 = {result}, 获取到的ID = {doctorId}");
                            
                            // 处理标签
                            if (!string.IsNullOrEmpty(labelsStr))
                            {
                                var labelsList = labelsStr.Split(',', StringSplitOptions.RemoveEmptyEntries);
                                foreach (var labelName in labelsList)
                                {
                                    if (labelMap.TryGetValue(labelName.Trim(), out int labelId))
                                    {
                                        // 创建医生-标签关联
                                        var doctorLabel = new DoctorLabelModel
                                        {
                                            DoctorId = doctorId,
                                            LaberId = labelId,
                                            IsDeleted = false
                                        };
                                        await doctorLabelRepo.CreateAsync(doctorLabel);
                                    }
                                }
                            }
                            
                            importResult.SuccessCount++;
                        }
                        catch (Exception ex)
                        {
                            importResult.ErrorMessages.Add($"第{row}行处理异常: {ex.Message}");
                            importResult.FailedCount++;
                        }
                    }
                }
                
                return Ok(new { 
                    Message = $"导入完成: 总计{importResult.TotalRows}条数据，成功{importResult.SuccessCount}条，失败{importResult.FailedCount}条", 
                    Result = importResult
                });
            }
            catch (Exception ex)
            {
                return BadRequest($"导入过程中发生错误: {ex.Message}");
            }
        }
        
        // 导入结果DTO
        public class ImportResultDto
        {
            public int TotalRows { get; set; }
            public int SuccessCount { get; set; }
            public int FailedCount { get; set; }
            public List<string> ErrorMessages { get; set; }
        }
        /// <summary>
        /// 导出所有医生信息为Excel
        /// </summary>
        [HttpGet]
        public async Task<IActionResult> Export(
            [FromServices] IBaseRepository<DoctorModel> doctorRepo,
            [FromServices] IBaseRepository<ManageModel> departmentRepo,
            [FromServices] IBaseRepository<CampusModel> campusRepo,
            [FromServices] IBaseRepository<JobTitleModel> jobTitleRepo,
            [FromServices] IBaseRepository<LabelModel> labelRepo,
            [FromServices] IBaseRepository<DoctorLabelModel> doctorLabelRepo,
            [FromQuery] string? doctorName = null,
            [FromQuery] int departmentId = 0)
        {
            try
            {
                // 添加调试日志，确认方法被调用
                Console.WriteLine("Export 方法被调用");
                
                // 直接从数据库查询医生数据
                Console.WriteLine("开始从数据库查询医生数据");
                
                // 获取所有未删除的医生、科室、校区和标签数据
                var doctors = doctorRepo.GetAll().Where(a => !a.IsDeleted);
                var departments = departmentRepo.GetAll().Where(a => !a.IsDeleted);
                var campuses = campusRepo.GetAll().Where(a => !a.IsDeleted);
                var labels = labelRepo.GetAll().Where(a => !a.IsDeleted);
                var doctorLabels = doctorLabelRepo.GetAll().Where(a => !a.IsDeleted);
                var jobTitles = jobTitleRepo.GetAll().Where(a => !a.IsDeleted);

                // 应用筛选条件
                if (departmentId > 0)
                {
                    doctors = doctors.Where(a => a.DepartmentId == departmentId);
                }

                if (!string.IsNullOrEmpty(doctorName))
                {
                    doctors = doctors.Where(a => a.DoctorName.Contains(doctorName));
                }

                // 使用LINQ连接查询获取完整的医生信息
                var query = from doctor in doctors
                            join department in departments on doctor.DepartmentId equals department.Id into deptJoin
                            from dept in deptJoin.DefaultIfEmpty()
                            join campus in campuses on doctor.CampusId equals campus.Id into campusJoin
                            from camp in campusJoin.DefaultIfEmpty()
                            join jobTitle in jobTitles on doctor.JobTitleId equals jobTitle.Id into jobJoin
                            from job in jobJoin.DefaultIfEmpty()
                            select new
                            {
                                Doctor = doctor,
                                DepartmentName = dept != null ? dept.DepartmentName : string.Empty,
                                CampusName = camp != null ? camp.CampusName : string.Empty,
                                JobTitle = job != null ? job.JobTitle : string.Empty
                            };

                // 执行查询并获取结果
                var doctorList = query.ToList();
                
                Console.WriteLine($"从数据库查询到医生数据: {doctorList.Count} 条");
                
                // 如果没有数据，返回提示
                if (doctorList.Count == 0)
                {
                    return BadRequest("没有找到医生数据，无法导出");
                }
                
                // 构建包含标签的医生数据列表
                var allDoctors = new List<DoctorExportDto>();
                foreach (var item in doctorList)
                {
                    // 获取医生的标签
                    var doctorLabelsQuery = from dl in doctorLabels
                                           where dl.DoctorId == item.Doctor.Id
                                           join l in labels on dl.LaberId equals l.Id
                                           select new LabelDto { Label = l.Label };
                    
                    var doctorLabelsList = doctorLabelsQuery.ToList();
                    
                    // 创建导出DTO
                    allDoctors.Add(new DoctorExportDto
                    {
                        DoctorName = item.Doctor.DoctorName,
                        CampusName = item.CampusName,
                        DepartmentName = item.DepartmentName,
                        JobTitle = item.JobTitle,
                        Briefly = item.Doctor.Briefly,
                        Labels = doctorLabelsList,
                        Status = item.Doctor.Status
                    });
            }

                // 创建Excel工作簿
            var workbook = new XSSFWorkbook();
            var sheet = workbook.CreateSheet("医生信息");
                
                // 创建表头
                var headerRow = sheet.CreateRow(0);
                var headers = new[] { "医生姓名", "院区", "科室", "职称", "简介", "标签", "状态" };
                for (int i = 0; i < headers.Length; i++)
                {
                    var cell = headerRow.CreateCell(i);
                    cell.SetCellValue(headers[i]);
                }

                // 填充数据
                int rowIndex = 1;
                foreach (var doctor in allDoctors)
            {
                    var dataRow = sheet.CreateRow(rowIndex++);
                    dataRow.CreateCell(0).SetCellValue(doctor.DoctorName ?? "");
                    dataRow.CreateCell(1).SetCellValue(doctor.CampusName ?? "");
                    dataRow.CreateCell(2).SetCellValue(doctor.DepartmentName ?? "");
                    dataRow.CreateCell(3).SetCellValue(doctor.JobTitle ?? "");
                    dataRow.CreateCell(4).SetCellValue(doctor.Briefly ?? "");
                    dataRow.CreateCell(5).SetCellValue(doctor.Labels != null ? string.Join(",", doctor.Labels.Select(l => l.Label)) : "");
                    dataRow.CreateCell(6).SetCellValue(doctor.Status ? "启用" : "停用");
            }

                // 自动调整列宽
                for (int i = 0; i < headers.Length; i++)
                {
                    sheet.AutoSizeColumn(i);
                }

                // 写入内存流
            var stream = new MemoryStream();
                try
                {
            workbook.Write(stream, true);
            stream.Position = 0;
                    Console.WriteLine($"生成的Excel文件大小: {stream.Length} 字节");
                    
                    if (stream.Length == 0)
                        return BadRequest("生成的Excel文件为空");
                    
                    // 返回文件
                    return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"医生信息导出_{DateTime.Now:yyyyMMdd}.xlsx");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Excel生成异常: {ex.Message}");
                    return BadRequest("Excel生成失败: " + ex.Message);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"导出过程中发生异常: {ex.Message}");
                Console.WriteLine($"异常堆栈: {ex.StackTrace}");
                return BadRequest($"导出失败: {ex.Message}");
            }
        }

        // 导出用DTO
        public class DoctorExportDto
        {
            public string DoctorName { get; set; }
            public string CampusName { get; set; }
            public string DepartmentName { get; set; }
            public string JobTitle { get; set; }
            public string Briefly { get; set; }
            public List<LabelDto> Labels { get; set; }
            public bool Status { get; set; }
        }
        
        public class LabelDto 
        {
            public string Label { get; set; } 
        }
    }
} 